package org.tlang.ast.list.func;

import org.tlang.ast.AST;
import org.tlang.ast.ASTList;
import org.tlang.context.SymbolTable;
import org.tlang.context.TypeTable;
import org.tlang.context.ValueTable;
import org.tlang.exception.TypeException;
import org.tlang.metaclass.TVar;
import org.tlang.type.Type;
import org.tlang.type.VoidType;

import java.util.List;

/**
 * 形参列表
 */
public class ParameterList extends ASTList {
    private int[] offsets;
    private Type[] types;

    public ParameterList(List<AST> children) {
        super(children);
    }

    private Parameter parameter(int i) {
        return (Parameter) child(i);
    }

    public int[] offsets() {
        return offsets;
    }

    Type[] types(TypeTable typeTable) {
        extractTypes(typeTable);
        return types;
    }

    @Override
    public void lookup(SymbolTable symbolTable, TypeTable typeTable) {
        int size = numChildren();
        offsets = new int[size];
        for (int i = 0; i < size; i++) {
            offsets[i] = symbolTable.add(parameter(i).name());
        }

        extractTypes(typeTable);
    }

    @Override
    public Type typeCheck(TypeTable typeTable) throws TypeException {
        extractTypes(typeTable);
        for (int i = 0; i < offsets.length; i++) {
            typeTable.put(offsets[i], this.types[i]);
        }
        return VoidType.VOID_TYPE;
    }

    private void extractTypes(TypeTable typeTable) {
        if (types != null) {
            return;
        }

        this.types = new Type[numChildren()];
        for (int i = 0; i < numChildren(); i++) {
            this.types[i] = parameter(i).type(typeTable);
        }
    }

    @Override
    public Object eval(ValueTable valueTable) {
        for (int offset : offsets) {
            valueTable.add(offset, new TVar(null)); // 向环境中注册变量定义，并初始化为null
        }

        return null;
    }

    @Override
    protected String toStringSep() {
        return ", ";
    }
}
